<?php
declare (strict_types = 1);
namespace app\admin\service;
use app\admin\model\AdminApi as AdminApiModel;
use app\admin\model\AdminMenuApi as AdminMenuApiModel;
use app\admin\model\AdminRoleMenu as AdminRoleMenuModel;
use app\admin\model\AdminUserRole as AdminUserRoleModel;
use app\admin\service\AdminUser as AdminUserService;
use app\admin\model\AdminMenu as AdminMenuModel;
/**
 * 超管后台权限验证服务
 * Class Auth
 * @package app\admin\service
 */
class Auth
{
    // 实例句柄
    static public $instance;

    // 超管登录信息
    private $admin;

    // 超管用户信息
    private $user;

    // 超管用户权限url
    private $apiUrls = [];

    /**
     * 公有化获取实例方法
     * @return Auth
     */
    public static function getInstance()
    {
        if (!(self::$instance instanceof Auth)) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    /**
     * 私有化构造方法
     * Auth constructor.
     */
    private function __construct()
    {
        // 超管登录信息
        $this->admin = AdminUserService::getLoginInfo();
        // 用户信息不存在
        if (empty($this->admin)) {
            return false;
        }
        // 当前用户信息
        $this->user = $this->admin['user'];
    }

    /**
     * 私有化克隆方法
     */
    private function __clone()
    {
    }

    /**
     * 验证指定url是否有访问权限
     * @param $url
     * @param bool $strict 严格模式($url必须全部有权)
     * @return bool
     */
    public function checkRoute($url, bool $strict = true)
    {
        if (!is_array($url)) {
            return $this->checkUrl($url);
        }
        foreach ($url as $val) {
            $status = $this->checkUrl($val);
            if ($strict && !$status) return false;
            if (!$strict && $status) return true;
        }
        return true;
    }

    /**
     * 验证url的权限
     * @param $url
     */
    private function checkUrl($url)
    {

        // 域名白名单
        // config/allowapi.php
        $allowApis = config('allowapi');
        // 验证当前请求是否在白名单
        if (in_array($url, $allowApis)) {
            return true;
        }
        // 用户不存在 禁止访问
        if (empty($this->user)) {
            return false;
        }
        // 超级管理员无需验证
        if ($this->user['is_super']) {
            return true;
        }
        // 通配符支持
        foreach ($allowApis as $action) {
            if (strpos($action, '*') !== false
                && preg_match('/^' . str_replace('/', '\/', $action) . '/', $url)
            ) {
                return true;
            }
        }

        // 获取当前用户的权限url列表
        if (!in_array($url, $this->getAdminUrls())) {
            return false;
        }
        return true;
    }

    /**
     * 获取当前用户的权限url列表
     * @return array
     */
    private function getAdminUrls()
    {
        if (empty($this->apiUrls)) {

            // 获取当前用户的角色组的所有ID集
            $adminRoleIds = AdminUserRoleModel::getRoleIdsByUserId($this->user['admin_user_id']);
            // 获取对应的所有角色组的已分配的菜单ID集
            $adminMenuIds = AdminRoleMenuModel::getMenuIds($adminRoleIds);
            // 获取已分配的所有角色组的菜单所对应API的ID集
            $adminApiIds = AdminMenuApiModel::getApiIds($adminMenuIds);
            // 获取当前角色所有权限url集
            $this->apiUrls = AdminApiModel::getApiUrls($adminApiIds);
        }

        return $this->apiUrls;
    }
    /**
     * [getAdminMenu 获取当前用户菜单权限]
     * Author：上官钧墨
     * @param  [type] $admin_user_id [description]
     * @return [type]                [description]
     */
    public function getAdminMenu($admin_user_id)
    {
        // 获取当前用户的角色组的所有ID集
        $adminRoleIds = AdminUserRoleModel::getRoleIdsByUserId($admin_user_id);
        // 获取对应的所有角色组的已分配的菜单ID集
        $adminMenuIds = AdminRoleMenuModel::getMenuIds($adminRoleIds);
        // 获取分配的菜单和权限
        $list = AdminMenuModel::getMenuIds($adminMenuIds);
        $menu = [];
        foreach ($list as $key => $value) {
            if (!$value['is_action']) {
                array_push($menu,[
                    'action'=>$this->getAction($list,$value['admin_menu_id']),
                    'name'=>$value['name'],
                    'path'=>$value['path']
                ]);
            }
        }
        return $menu;
    }
    /**
     * [获取操作权限]
     * Author：上官钧墨
     * @param  [type] $all           [description]
     * @param  [type] $admin_menu_id [description]
     */
    public function getAction($all,$admin_menu_id)
    {
        $list = [];
        foreach ($all as $v) {
            if ($v['is_action'] && $v['pid'] == $admin_menu_id) {
                array_push($list,[
                    'name'=>$v['name'],
                    'path'=>$v['path']
                ]);
            }
        }
        return $list;
    }
    /**
     * [children 生成菜单树]
     * Author：上官钧墨
     * @param  array  $all [所有数据]
     * @param  integer $pid [上级id]
     */
    private function children($all,$pid = 0){
        $list = [];
        foreach ($all as $v) {
            if (!$v['is_action']) {
                if ($v['pid'] == $pid) {
                    $item = $this->children($all,$v['admin_menu_id']);
                    $v['action'] = $this->getAction($all,$v['admin_menu_id']);
                    !empty($item) && $v['children'] = $item;
                    $list[] = $v;
                    unset($item);
                }
            }
        }
        return $list;
    }
}
